Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / local_message_retention.py

Displaying Raw • Download


meshchatx/src/backend/local_message_retention.py 9f75e3db181925ddd253f7fb231af81f9fb8c013 (9f75e3db) Text, 4.57 KB

T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Local-only age-based deletion of stored LXMF rows (this device, no network signal)."""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787logging
Tff7b72import T7ee787time
Tff7b72from T7ee787collectionsT7ee787.T7ee787abc Tff7b72import Te6edf3Callable
Tff7b72from T7ee787datetime Tff7b72import Te6edf3UTCTb4b4b4, Te6edf3dateTb4b4b4, Te6edf3datetime

Te6edf3log Tff7b72= Te6edf3loggingTff7b72.Td2a8ffgetLoggerTb4b4b4(Tff7b72__name__Tb4b4b4)

Te6edf3UNIT_DAYS Tff7b72= Ta5d6ff"Ta5d6ffdaysTa5d6ff"
Te6edf3UNIT_MONTHS Tff7b72= Ta5d6ff"Ta5d6ffmonthsTa5d6ff"

Te6edf3SECONDS_PER_DAY Tff7b72= T79c0ff86400
Te6edf3SECONDS_PER_MONTH Tff7b72= T79c0ff30 Tff7b72* Te6edf3SECONDS_PER_DAY

Te6edf3RETENTION_CHECK_INTERVAL_SECONDS Tff7b72= T79c0ff3600
Te6edf3LOCAL_RETENTION_STARTUP_GRACE_SECONDS Tff7b72= T79c0ff120

Te6edf3MAX_VALUE_DAYS Tff7b72= T79c0ff10_000
Te6edf3MAX_VALUE_MONTHS Tff7b72= T79c0ff120


Tff7b72def Td2a8ffnormalize_unitTb4b4b4(Te6edf3rawTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
Te6edf3s Tff7b72= Tb4b4b4(Te6edf3raw Tff7b72or Te6edf3UNIT_DAYSTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3s Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffmonthTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmonthsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmoTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3UNIT_MONTHS
Tff7b72return Te6edf3UNIT_DAYS


Tff7b72def Td2a8ffretention_window_secondsTb4b4b4(Te6edf3valueTb4b4b4: Tffa657intTb4b4b4, Te6edf3unitTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3v Tff7b72= Tffa657intTb4b4b4(Te6edf3valueTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Te6edf3v Tff7b72= T79c0ff1
Te6edf3u Tff7b72= Te6edf3normalize_unitTb4b4b4(Te6edf3unitTb4b4b4)
Tff7b72if Te6edf3u Tff7b72== Te6edf3UNIT_MONTHSTb4b4b4:
Tff7b72return Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657minTb4b4b4(Te6edf3vTb4b4b4, Te6edf3MAX_VALUE_MONTHSTb4b4b4)Tb4b4b4) Tff7b72* Te6edf3SECONDS_PER_MONTH
Tff7b72return Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657minTb4b4b4(Te6edf3vTb4b4b4, Te6edf3MAX_VALUE_DAYSTb4b4b4)Tb4b4b4) Tff7b72* Te6edf3SECONDS_PER_DAY


Tff7b72def Td2a8fflocal_message_retention_cutoff_tsTb4b4b4(Te6edf3nowTb4b4b4: Tffa657floatTb4b4b4, Te6edf3valueTb4b4b4: Tffa657intTb4b4b4, Te6edf3unitTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657floatTb4b4b4:
Tff7b72return Tffa657floatTb4b4b4(Te6edf3nowTb4b4b4) Tff7b72- Tffa657floatTb4b4b4(Te6edf3retention_window_secondsTb4b4b4(Te6edf3valueTb4b4b4, Te6edf3unitTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8ffparse_before_cutoffTb4b4b4(Te6edf3rawTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657float Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Parse a before cutoff from unix seconds or an ISO date/datetime string.

YYYY-MM-DD is treated as midnight UTC on that calendar day (messages with
timestamp strictly before that instant).
"""
Tff7b72if Te6edf3raw Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Tffa657strTb4b4b4(Te6edf3rawTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72return Tffa657floatTb4b4b4(Te6edf3sTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Tff7b72pass
Tff7b72tryTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3sTb4b4b4) Tff7b72== T79c0ff10 Tff7b72and Te6edf3sTb4b4b4[T79c0ff4Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ff-Ta5d6ff" Tff7b72and Te6edf3sTb4b4b4[T79c0ff7Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ff-Ta5d6ff"Tb4b4b4:
Te6edf3d Tff7b72= Te6edf3dateTff7b72.Td2a8fffromisoformatTb4b4b4(Te6edf3sTb4b4b4)
Tff7b72return Te6edf3datetimeTb4b4b4(Te6edf3dTff7b72.Td2a8ffyearTb4b4b4, Te6edf3dTff7b72.Td2a8ffmonthTb4b4b4, Te6edf3dTff7b72.Td2a8ffdayTb4b4b4, Te6edf3tzinfoTff7b72=Te6edf3UTCTb4b4b4)Tff7b72.Td2a8fftimestampTb4b4b4(Tb4b4b4)
Te6edf3dt Tff7b72= Te6edf3datetimeTff7b72.Td2a8fffromisoformatTb4b4b4(Te6edf3sTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ffZTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff+00:00Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3dtTff7b72.Td2a8fftzinfo Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3dt Tff7b72= Te6edf3dtTff7b72.Td2a8ffreplaceTb4b4b4(Te6edf3tzinfoTff7b72=Te6edf3UTCTb4b4b4)
Tff7b72return Te6edf3dtTff7b72.Td2a8fftimestampTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3excTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid before valueTa5d6ff"Tb4b4b4) Tff7b72from T7ee787exc


Tff7b72def Td2a8ffresolve_message_age_cutoffTb4b4b4(
Tff7b72*Tb4b4b4,
Te6edf3older_than_daysTb4b4b4: Tffa657str Tff7b72| Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3beforeTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3nowTb4b4b4: Tffa657float Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657float Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Resolve a purge/export cutoff from query-style inputs.

Returns None when neither filter is provided. Prefer ``before`` when both
are set. Raises ValueError on invalid input.
"""
Te6edf3before_raw Tff7b72= Tff7b72None Tff7b72if Te6edf3before Tff7b72is Tff7b72None Tff7b72else Tffa657strTb4b4b4(Te6edf3beforeTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3before_rawTb4b4b4:
Te6edf3cutoff Tff7b72= Te6edf3parse_before_cutoffTb4b4b4(Te6edf3before_rawTb4b4b4)
Tff7b72if Te6edf3cutoff Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid before valueTa5d6ff"Tb4b4b4)
Tff7b72return Tffa657floatTb4b4b4(Te6edf3cutoffTb4b4b4)

Tff7b72if Te6edf3older_than_days Tff7b72is Tff7b72None Tff7b72or Tffa657strTb4b4b4(Te6edf3older_than_daysTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff"Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3days Tff7b72= Tffa657intTb4b4b4(Te6edf3older_than_daysTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffolder_than_days must be an integerTa5d6ff"Tb4b4b4) Tff7b72from T7ee787exc
Tff7b72if Te6edf3days Tff7b72< T79c0ff1 Tff7b72or Te6edf3days Tff7b72> Te6edf3MAX_VALUE_DAYSTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffolder_than_days must be between 1 and Tffd700{Te6edf3MAX_VALUE_DAYSTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3local_message_retention_cutoff_tsTb4b4b4(
Te6edf3now Tff7b72if Te6edf3now Tff7b72is Tff7b72not Tff7b72None Tff7b72else Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3daysTb4b4b4,
Te6edf3UNIT_DAYSTb4b4b4,
Tb4b4b4)


Tff7b72def Td2a8ffpurge_messages_before_cutoffTb4b4b4(
Te6edf3messagesTb4b4b4,
Te6edf3cancel_outboundTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657bytesTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4,
Te6edf3cutoffTb4b4b4: Tffa657floatTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Delete local LXMF rows with timestamp strictly before cutoff.

Attachments live in message row fields, so deleting the row removes them.
Does not contact peers.
"""
Te6edf3hashes Tff7b72= Te6edf3messagesTff7b72.Td2a8fflist_message_hashes_with_timestamp_beforeTb4b4b4(Tffa657floatTb4b4b4(Te6edf3cutoffTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3hashesTb4b4b4:
Tff7b72return T79c0ff0
Tff7b72if Te6edf3cancel_outbound Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72for Te6edf3h Tff7b72in Te6edf3hashesTb4b4b4:
Tff7b72if Tff7b72not Te6edf3h Tff7b72or Tffa657lenTb4b4b4(Te6edf3hTb4b4b4) Tff7b72% T79c0ff2 Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3cancel_outboundTb4b4b4(Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4: T8b949e# noqa: BLE001
Te6edf3logTff7b72.Td2a8ffdebugTb4b4b4(Ta5d6ff"Ta5d6ffpurge_messages_before_cutoff cancel_outbound: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Te6edf3messagesTff7b72.Td2a8ffdelete_lxmf_messages_by_hashesTb4b4b4(Te6edf3hashesTb4b4b4)
Te6edf3messagesTff7b72.Td2a8ffprune_conversation_metadata_for_peers_with_no_messagesTb4b4b4(Tb4b4b4)
Tff7b72return Tffa657lenTb4b4b4(Te6edf3hashesTb4b4b4)


Tff7b72def Td2a8ffapply_local_message_retentionTb4b4b4(
Te6edf3messagesTb4b4b4,
Te6edf3cancel_outboundTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657bytesTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3valueTb4b4b4: Tffa657intTb4b4b4,
Te6edf3unitTb4b4b4: Tffa657strTb4b4b4,
Te6edf3nowTb4b4b4: Tffa657floatTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Delete local LXMF message rows older than the retention window.

Does not contact peers; only removes rows from the local database.
"""
Te6edf3cutoff Tff7b72= Te6edf3local_message_retention_cutoff_tsTb4b4b4(Te6edf3nowTb4b4b4, Te6edf3valueTb4b4b4, Te6edf3unitTb4b4b4)
Tff7b72return Te6edf3purge_messages_before_cutoffTb4b4b4(Te6edf3messagesTb4b4b4, Te6edf3cancel_outboundTb4b4b4, Te6edf3cutoffTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────